package com.cskaoyan.javase.oop.block9.static3;

/**
 * @description: 静态代码块
 * @author: wuguidong@cskaoyan.onaliyun.com
 **/

/**
 * 静态代码块：用static修饰的构造代码块就是静态代码块
 * 语法：static{}
 * 位置：成员位置
 * 作用：就是给静态成员变量赋值，随着类加载而执行其中的代码，这些代码仅执行一次
 * 这个其实区别就是静态成员变量和普通成员变量的区别
 *
 * 总结目前给静态成员赋值的方法：
 *  1，显式赋值初始化
 *  2，静态代码块
 *  以上两种是类加载赋值，以下是随着创建对象执行的
 *  3，构造代码块
 *  4，构造器，构造方法
 *
 *  先来研究1，2的顺序，现在我不说，你们想一下，这里和代码顺序有无关系？
 *  1，2的顺序是依赖于代码中书写的顺序的，同样的除非你是出面试题，不然不要把静态代码块写在上面
 *
 *  1，2全体和3，4的顺序是什么？ 由于类加载永远在创建对象之前，
 *  所以1，2永远在3，4前面，并且1，2的执行顺序和代码顺序有关
 *
 *  需要注意的是：
 * - 静态代码块和静态成员一样，不能在里面调用非静态
 * - 除非是静态成员变量需要很复杂的初始化代码，否则没太大必要使用，直接显式赋值就行
 * - 静态代码块和静态成员变量的定义顺序，也会影响到静态成员变量的最终取值
 *   - 所以应该永远将静态代码块放在静态成员变量的定义下面
 * - 构造代码块可以给静态成员变量赋值，静态代码块却不能给普通成员代码块赋值
 *   - 若构造代码块和静态代码块同时给一个静态成员变量赋值
 *     - 它们在代码中的顺序，并不会对结果造成影响
 *   - 因为静态代码块总是先于构造代码块执行
 *
 */
public class Demo {
    public static void main(String[] args) {
        //这里虽然没有创建对象，但是调用了静态成员，也触发了类加载
        System.out.println(Dog.color); //结果是什么？ 这里仍然是白色
        Dog dog = new Dog();
        System.out.println(Dog.color); //结果是什么？ 这里构造代码块执行力，所以变绿了
    }
}

class Dog{
    {
        color = "绿色";
    }
    static {
        color = "黄色";
        //这里不能调用普通成员变量,也不能用this和super
    }
    int age;
    //静态的颜色
    static String color = "白色";
    //声明了一个静态代码块

    public Dog() {
    }
}
